/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef __IHDRSCENE_H__
#define __IHDRSCENE_H__

#pragma once

#include "IScene.h"
#include "ITexture.h"
#include "IShaderEffect.h"
#include "IFont.h"
#include "IModel.h"

/*****************************************************************
 *                                                               *
 *   A specialized scene interface that handles HDR rendering.   *
 *                                                               *
 *****************************************************************/
class DLL_EXPORT IHDRScene 
	: public IScene
{
public:
	IHDRScene(void);
	virtual ~IHDRScene(void);

	// Initialize the scene and all it's content
	virtual bool init();

	// Updates all the objects in the scene. dt is in seconds
	virtual void update(double dt);
	
	// Draws the scene
	virtual void draw();

	// Called upon destruction of the object
	virtual void destroy();

	// Called by the core's rendering loop. Please use the draw() function instead
	virtual void drawScene();

	// Manually sets the exposure
	virtual void setExposure(float exposure);

	// Manually sets the gamma value
	void setGamma(float gamma);

	const float getGamma() const { return fGamma; }

	// Enables / disables rendering of bloom
	virtual void setRenderBloom(bool value);

	virtual void release();
	virtual void restore();

	virtual bool isHDRScene() const { return true; }

protected:
	/// Calculate the average luminance of the scene
	void getSampleOffsets(int iWidth, int iHeight, math::Vector2f sampleOffsets[]);
	/// Calculate the luminance of the scene
	void calculateLuminance();
	/// Do a texture pass
	void texturePass(const std::string &technique, ITexture *target, ITexture *textureA, ITexture *textureB = NULL);

	ITexture *hdrRenderTarget;			///< The full screen render target for HDR rendering
	ITexture *hdrRenderTargetScaled;	///< A scaled render target for effects
	ITexture *hdrRenderTargetHighPass;	///< A scaled rendering target for high pass
	ITexture *hdrRenderTargetBlurX;		///< A scaled rendering target blurred in X direction
	ITexture *hdrRenderTargetBlurY;		///< A scaled rendering target blurred in Y direction

	ITexture *hdrLumCurrent;			///< Holds the current luminance value
	ITexture *hdrLumLast;				///< Holds the last luminance value
	ITexture *hdrLuminance[4];			///< Four temporary luminance textures at different scales

	IShaderEffect  *hdrRenderEffect;	///< The effect for handling bloom and tone mapping

	float fExposure, fGamma, fVignetting;

	int  iCropWidth, iCropHeight;

	bool bRenderBloom;

	float fFrameDelta;

private:
	SHADERHANDLE smallHDRTextureHighPass;
	SHADERHANDLE blurTexture;
	SHADERHANDLE textureA;
	SHADERHANDLE textureB;
	SHADERHANDLE renderBloom;
	SHADERHANDLE hPixelOffset;
	SHADERHANDLE hExposureLevel;
	SHADERHANDLE hGammaLevel;
	SHADERHANDLE hVignettingStrength;
	SHADERHANDLE hAVSampleOffsets;
	SHADERHANDLE hElapsedTime;
	SHADERHANDLE hBlurSamplerSize;
	SHADERHANDLE hTexWidthHeight;

	bool firstDraw;
};

#endif
